﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MVCPets.Extensions;
using System.Text.RegularExpressions;

namespace MVCPets.Tests.Extensions
{
  [TestClass]
  public class StringExtensionTests
  {
    [TestMethod]
    public void Test_SubstringIndex()
    {
      var baseString = "this is a test of the emergency broadcast system!";

      Assert.IsTrue(baseString.SubstringIndex("test").Length > 0);
      Assert.IsTrue(baseString.SubstringIndex("test").Length < baseString.Length);
      Assert.IsTrue(baseString.SubstringIndex("alfalpha") == baseString);
    }

    [TestMethod]
    public void Test_ISO8859()
    {
      var foo = "María";
      var bar = "MarÃ­a";

      Assert.AreEqual(foo, bar.FromIso8859String());
      Assert.AreEqual(bar, foo.ToIso8859String());
    }

    [TestMethod]
    public void Test_Compress()
    {
      string data = "datadata";
      string result = data.Compress();
      Assert.IsTrue(!data.Equals(result));
      string result2 = result.Decompress();

      Assert.IsTrue(data.Equals(result2));
    }

    [TestMethod]
    public void Test_Encryption()
    {
      string data = "datadata";
      string result = data.Encrypt();
      Assert.IsTrue(!data.Equals(result));
      string result2 = result.Decrypt();

      Assert.IsTrue(data.Equals(result2));
    }

    [TestMethod]
    public void Test_Cannot_Decrypt_Bad_String()
    {
      string result2 = "SomebadDataHEre".Decrypt();
      Assert.IsTrue(result2.Equals(""));
    }

    [TestMethod]
    public void Can_URL_Encode()
    {
      string result = " ".UrlEncode();
      Assert.IsTrue(result.Equals("+"));
    }

    [TestMethod]
    public void Can_URL_Decode()
    {
      string result = "+".UrlDecode();
      Assert.IsTrue(result.Equals(" "));
    }

    [TestMethod]
    public void Can_Html_Encode()
    {
      string result = "<".HtmlEncode();
      Assert.IsTrue(result.Equals("&lt;"));
    }

    [TestMethod]
    public void Can_Html_Decode()
    {
      string result = "&lt;".HtmlDecode();
      Assert.IsTrue(result.Equals("<"));
    }

    [TestMethod]
    public void Test_Contains()
    {
      Assert.IsTrue("sometestjunk".Contains("test", StringComparison.CurrentCultureIgnoreCase));
    }

    [TestMethod]
    public void Test_Contains_Rejex()
    {
      Assert.IsTrue("a@a.com".Contains(@"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)$", RegexOptions.Compiled));
    }

    [TestMethod]
    public void Test_Extract_Before()
    {
      Assert.IsTrue("sometestjunk".ExtractBefore("test").Equals("some"));
    }

    [TestMethod]
    public void Test_Extract_After()
    {
      Assert.IsTrue("sometestjunk".ExtractAfter("test").Equals("junk"));
    }

    [TestMethod]
    public void Test_HasValue()
    {
      Assert.IsTrue("1".HasValue());
      Assert.IsFalse("".HasValue());
    }

    [TestMethod]
    public void Test_IsNullOrEmpty()
    {
      Assert.IsFalse("1".IsNullOrEmpty());
      Assert.IsTrue("".IsNullOrEmpty());
    }

    [TestMethod]
    public void Test_Right()
    {
      Assert.IsTrue("12345".Right(2).Equals("45"));
      Assert.IsTrue("12345".Right(5).Equals("12345"));
    }

    [TestMethod]
    public void Test_Left()
    {
      Assert.IsTrue("12345".Left(2).Equals("12"));
      Assert.IsTrue("12345".Left(5).Equals("12345"));
    }

    [TestMethod]
    public void Test_Truncate()
    {
      Assert.IsTrue("123456".Truncate(0).Equals("123456"));
      Assert.IsTrue("123456".Truncate(-1).Equals("123456"));
      Assert.IsTrue("123456".Truncate(6).Equals("123456"));
      Assert.IsTrue("1".Truncate(6).Equals("1"));
      Assert.IsTrue("123".Truncate(6).Equals("123"));
      Assert.IsTrue("123456".Truncate(1).Equals("123456"));
      Assert.IsTrue("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ".Truncate(5) == "12...");
    }

    [TestMethod]
    public void Test_Parse()
    {
      Assert.IsTrue("true".Parse<bool>());
    }

    [TestMethod, ExpectedException(typeof(FormatException))]
    public void Test_Bad_Parse()
    {
      Assert.IsTrue("FooYou".Parse<bool>());
    }

    [TestMethod]
    public void Test_Safe_Parse()
    {
      Assert.IsTrue("true".SafeParse<bool>());
    }

    [TestMethod]
    public void Test_Bad_Safe_Parse()
    {
      Assert.IsFalse("FooYou".SafeParse<bool>());
    }

    [TestMethod]
    public void Test_Format_String()
    {
      Assert.IsTrue("Foo{0}".FormatString("bar").Equals("Foobar"));
      Assert.IsTrue("Foo{0}{1}".FormatString("bar", "hard").Equals("Foobarhard"));
    }

    [TestMethod]
    public void Test_ToFormattedString()
    {
      Assert.IsTrue("Foo{0}{1}{2}".ToFormattedString(1, 2, 3).Equals("Foo123"));
    }

    [TestMethod]
    public void Test_Can_Get_Unicode()
    {
      Assert.IsTrue(74.AsciiToUnicode() == "J");
    }

    [TestMethod]
    public void Test_Can_Get_String_From_List()
    {
      Assert.IsTrue(new List<string> { "1", "2" }.ToDelimitedList() == "1,2");
      Assert.IsTrue(new List<string> { "1", "2" }.ToDelimitedList("|") == "1|2");
    }

    [TestMethod]
    public void Test_Matches()
    {
      Assert.IsTrue("1".Matches("1"));
      Assert.IsFalse("1".Matches("2"));
    }

    [TestMethod]
    public void Test_Matches_Trimmed()
    {
      Assert.IsTrue("1 ".MatchesTrimmed("1"));
      Assert.IsFalse("1 ".MatchesTrimmed("2"));
      Assert.IsTrue("1".MatchesTrimmed("1 "));
      Assert.IsFalse("1".MatchesTrimmed("2 "));
    }

    [TestMethod]
    public void Test_Regex_Match()
    {
      Assert.IsTrue("a@a.com".MatchesRegex(@"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)$"));
    }

    [TestMethod]
    public void Test_Chop()
    {
      Assert.IsTrue("12345".Chop("5") == "1234");
    }

    [TestMethod]
    public void Test_PluralToSingular()
    {
      Assert.IsTrue("Tests".PluralToSingular().Equals("Test"));
    }

    [TestMethod]
    public void Test_SingularToPlural()
    {
      Assert.IsTrue("Test".SingularToPlural().Equals("Tests"));
    }

    [TestMethod]
    public void Test_Pluralize()
    {
      Assert.IsTrue(1.Pluralize("Test") == "1 Test");
      Assert.IsTrue(2.Pluralize("Test") == "2 Tests");
    }

    [TestMethod]
    public void Test_Concatinate()
    {
      Assert.IsTrue("test".Concatinate("1").Equals("test1"));
      Assert.IsTrue("test".Concatinate("1", "2").Equals("test12"));
      Assert.IsTrue("test".Concatinate("1", "2", "3").Equals("test123"));

      Assert.IsTrue("test".Concatinate(1).Equals("test1"));
      Assert.IsTrue("test".Concatinate(1, 2).Equals("test12"));
      Assert.IsTrue("test".Concatinate(1, 2, 3).Equals("test123"));
    }

    [TestMethod]
    public void Test_Clip()
    {
      Assert.IsTrue("test".Clip(1).Equals("est"));
      Assert.IsTrue("test".Clip("st").Equals("st"));
      Assert.IsTrue("test".Clip().Equals("est"));
    }

    [TestMethod]
    public void Test_Fast_Replace()
    {
      Assert.IsTrue("test".FastReplace("st", "2").Equals("te2"));
      Assert.IsTrue("test".FastReplace("", "2").Equals("test"));
      string s = null;
      Assert.IsTrue(s.FastReplace("", "2") == null);
    }

    [TestMethod]
    public void Test_Crop()
    {
      Assert.IsTrue("foot".Crop("f", "t").Equals("oo"));
      Assert.IsTrue("foot".Crop("x", "t").Equals(""));
      Assert.IsTrue("foot".Crop("f", "x").Equals(""));
    }

    [TestMethod]
    public void Test_Squeeze()
    {
      Assert.IsTrue("something     here".Squeeze().Equals("something here"));
    }

    [TestMethod]
    public void Test_ToAlpha()
    {
      Assert.IsTrue("adc123^".ToAlphaNumericOnly().Equals("adc123"));
    }

    [TestMethod]
    public void Test_To_Words()
    {
      string[] words = "something here".ToWords();
      Assert.IsTrue(words[0].Equals("something"));
      Assert.IsTrue(words[1].Equals("here"));
    }

    [TestMethod]
    public void Strip_Html()
    {
      Assert.IsTrue(@"&nbsp;&amp;&gt;&lt;Hello".StripHTML() == "&><Hello");
    }

    [TestMethod]
    public void Test_Regex_Replace()
    {
      Assert.IsTrue("a@a.com".ReplaceRegex(@"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)$", "test", RegexOptions.IgnoreCase).Equals("test"));
    }

    [TestMethod]
    public void Test_Find_Matches()
    {
      List<string> results = "a@a.com".FindMatches(@"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)$");
      Assert.IsTrue(results[0].Equals("a@a.com"));
    }

    [TestMethod]
    public void Test_ScrambleString()
    {
      string input = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

      Assert.IsTrue(!input.ScrambleString().Equals("adc123"));
    }

    [TestMethod]
    public void Test_EscapeJS()
    {
      var sng = @"\'";
      var dbl = @"\""'";

      var input = "Phil's test \"course\"";
      var output = input.EscapeJs();

      Assert.IsTrue(output.Contains(sng));
      Assert.IsTrue(output.Contains(dbl));
    }

    [TestMethod]
    public void Test_Reverse_String()
    {
      Assert.IsTrue("tirehni".ReverseString() == "inherit");
    }

    [TestMethod]
    public void Test_Palindrome()
    {
      Assert.IsTrue("radar".IsPalindrome());
    }
  }
}
